"""Sentiment analysis for text content"""

from typing import Dict, Any, Optional, List, Tuple
import logging
from snownlp import SnowNLP
from textblob import TextBlob
import re

from .base_cleaner import BaseCleaner

logger = logging.getLogger(__name__)


class SentimentAnalyzer(BaseCleaner):
    """Analyze sentiment of text content
    
    Supports Chinese (SnowNLP) and English (TextBlob) sentiment analysis
    """
    
    def __init__(self, config: Optional[Dict[str, Any]] = None):
        """Initialize sentiment analyzer
        
        Args:
            config: Configuration with options:
                - analyze_sentences: Analyze individual sentences (default: False)
                - neutral_threshold: Threshold for neutral sentiment (default: 0.1)
                - language_detection: Auto-detect language (default: True)
        """
        super().__init__(config)
        self.analyze_sentences = self.config.get('analyze_sentences', False)
        self.neutral_threshold = self.config.get('neutral_threshold', 0.1)
        self.language_detection = self.config.get('language_detection', True)
        
        # Statistics
        self.stats = {
            'analyzed': 0,
            'positive': 0,
            'negative': 0,
            'neutral': 0
        }
    
    def clean(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """Analyze sentiment of text data
        
        Args:
            data: Input data dictionary
            
        Returns:
            Data with sentiment analysis results
        """
        # Extract text for analysis
        text = self._extract_text_for_sentiment(data)
        
        if not text:
            return data
        
        # Analyze sentiment
        sentiment_result = self._analyze_sentiment(text)
        
        # Add to cleaned data
        if 'cleaned_data' not in data:
            data['cleaned_data'] = {}
        
        data['cleaned_data']['sentiment'] = sentiment_result
        
        # Update statistics
        self.stats['analyzed'] += 1
        self.stats[sentiment_result['label']] += 1
        
        return data
    
    def _extract_text_for_sentiment(self, data: Dict[str, Any]) -> str:
        """Extract text content for sentiment analysis
        
        Args:
            data: Data dictionary
            
        Returns:
            Combined text content
        """
        text_parts = []
        
        # Title
        if 'title' in data and data['title']:
            text_parts.append(str(data['title']))
        
        # Main content
        if 'content' in data and data['content']:
            if isinstance(data['content'], str):
                text_parts.append(data['content'])
            elif isinstance(data['content'], dict):
                # Extract main text content
                for key in ['description', 'text', 'body', 'summary']:
                    if key in data['content'] and data['content'][key]:
                        text_parts.append(str(data['content'][key]))
                
                # Include comments for sentiment analysis
                if 'comments' in data['content']:
                    comments = data['content']['comments']
                    if isinstance(comments, list):
                        for comment in comments[:10]:  # Limit to first 10 comments
                            if isinstance(comment, str):
                                text_parts.append(comment)
                            elif isinstance(comment, dict) and 'text' in comment:
                                text_parts.append(str(comment['text']))
        
        # Description
        if 'description' in data and data['description']:
            text_parts.append(str(data['description']))
        
        return ' '.join(text_parts)
    
    def _analyze_sentiment(self, text: str) -> Dict[str, Any]:
        """Analyze sentiment of text
        
        Args:
            text: Input text
            
        Returns:
            Sentiment analysis result dictionary
        """
        if not text:
            return {
                'score': 0.0,
                'label': 'neutral',
                'confidence': 0.0
            }
        
        # Detect language
        has_chinese = self._has_chinese(text) if self.language_detection else False
        
        if has_chinese:
            result = self._analyze_chinese_sentiment(text)
        else:
            result = self._analyze_english_sentiment(text)
        
        # Analyze sentences if configured
        if self.analyze_sentences:
            result['sentences'] = self._analyze_sentence_sentiments(text, has_chinese)
        
        return result
    
    def _has_chinese(self, text: str) -> bool:
        """Check if text contains Chinese characters
        
        Args:
            text: Text to check
            
        Returns:
            True if text contains Chinese
        """
        chinese_pattern = re.compile(r'[\u4e00-\u9fff]+')
        matches = chinese_pattern.findall(text)
        chinese_chars = sum(len(match) for match in matches)
        
        # Consider it Chinese if more than 30% characters are Chinese
        return chinese_chars > len(text) * 0.3
    
    def _analyze_chinese_sentiment(self, text: str) -> Dict[str, Any]:
        """Analyze sentiment of Chinese text using SnowNLP
        
        Args:
            text: Chinese text
            
        Returns:
            Sentiment analysis result
        """
        try:
            # SnowNLP sentiment score ranges from 0 (negative) to 1 (positive)
            snow = SnowNLP(text)
            raw_score = snow.sentiments
            
            # Convert to -1 to 1 scale
            score = (raw_score - 0.5) * 2
            
            # Determine label
            if abs(score) < self.neutral_threshold:
                label = 'neutral'
            elif score > 0:
                label = 'positive'
            else:
                label = 'negative'
            
            # Calculate confidence (distance from neutral)
            confidence = min(abs(score) * 2, 1.0)
            
            return {
                'score': round(score, 4),
                'label': label,
                'confidence': round(confidence, 4),
                'raw_score': round(raw_score, 4),
                'analyzer': 'SnowNLP'
            }
            
        except Exception as e:
            logger.error(f"Error in Chinese sentiment analysis: {e}")
            return {
                'score': 0.0,
                'label': 'neutral',
                'confidence': 0.0,
                'error': str(e)
            }
    
    def _analyze_english_sentiment(self, text: str) -> Dict[str, Any]:
        """Analyze sentiment of English text using TextBlob
        
        Args:
            text: English text
            
        Returns:
            Sentiment analysis result
        """
        try:
            # TextBlob polarity ranges from -1 (negative) to 1 (positive)
            blob = TextBlob(text)
            polarity = blob.sentiment.polarity
            subjectivity = blob.sentiment.subjectivity
            
            # Determine label
            if abs(polarity) < self.neutral_threshold:
                label = 'neutral'
            elif polarity > 0:
                label = 'positive'
            else:
                label = 'negative'
            
            # Use subjectivity as part of confidence
            # High subjectivity means more confident in sentiment
            confidence = min(abs(polarity) * (0.5 + subjectivity * 0.5), 1.0)
            
            return {
                'score': round(polarity, 4),
                'label': label,
                'confidence': round(confidence, 4),
                'subjectivity': round(subjectivity, 4),
                'analyzer': 'TextBlob'
            }
            
        except Exception as e:
            logger.error(f"Error in English sentiment analysis: {e}")
            return {
                'score': 0.0,
                'label': 'neutral',
                'confidence': 0.0,
                'error': str(e)
            }
    
    def _analyze_sentence_sentiments(self, text: str, is_chinese: bool) -> List[Dict[str, Any]]:
        """Analyze sentiment of individual sentences
        
        Args:
            text: Text to analyze
            is_chinese: Whether text is Chinese
            
        Returns:
            List of sentence sentiment results
        """
        sentences = self._split_sentences(text)
        sentence_sentiments = []
        
        for sentence in sentences[:20]:  # Limit to first 20 sentences
            if len(sentence.strip()) < 5:  # Skip very short sentences
                continue
            
            if is_chinese:
                sentiment = self._analyze_chinese_sentiment(sentence)
            else:
                sentiment = self._analyze_english_sentiment(sentence)
            
            sentence_sentiments.append({
                'text': sentence[:100],  # Truncate long sentences
                'score': sentiment['score'],
                'label': sentiment['label']
            })
        
        return sentence_sentiments
    
    def _split_sentences(self, text: str) -> List[str]:
        """Split text into sentences
        
        Args:
            text: Text to split
            
        Returns:
            List of sentences
        """
        # Simple sentence splitting
        # For Chinese, split on Chinese punctuation
        chinese_pattern = r'[。！？；]+'
        english_pattern = r'[.!?;]+'
        
        # Try Chinese splitting first
        sentences = re.split(chinese_pattern, text)
        
        # If no Chinese punctuation, try English
        if len(sentences) <= 1:
            sentences = re.split(english_pattern, text)
        
        # Filter empty sentences
        return [s.strip() for s in sentences if s.strip()]
    
    def get_stats(self) -> Dict[str, Any]:
        """Get sentiment analysis statistics
        
        Returns:
            Statistics dictionary
        """
        stats = super().get_stats()
        stats['sentiment'] = self.stats.copy()
        
        if self.stats['analyzed'] > 0:
            total = self.stats['analyzed']
            stats['sentiment']['distribution'] = {
                'positive_ratio': self.stats['positive'] / total,
                'negative_ratio': self.stats['negative'] / total,
                'neutral_ratio': self.stats['neutral'] / total
            }
        
        return stats